home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / clang / text_eng.zip / WATCOM / TEXTURE.C < prev    next >
C/C++ Source or Header  |  1994-07-01  |  35KB  |  1,151 lines

  1. /*
  2.  *    TEXTURE.C    Version 1.0a  by Lee Lorenz      llorenz@delphi.com
  3.  *    *WATCOM VERSION*
  4.  *   First, Please excuse this mess.
  5.  *
  6.  *  Next, Welcome to high-speed image processing... My desire was to
  7.  *   rotate/scale a bitmap in real-time, and this was the result.
  8.  *   There were plenty of "examples" of texture mapping, in obfuscated
  9.  *   highly optimized assembly, but even the "C" and Pascal examples left
  10.  *   alot to be desired; after all, I wanted to have more freedom to display
  11.  *   images, and didn't want to bother with the trigonometry. With the simple
  12.  *   idea of "shooting" a line (Bresenham-style) through a source bitmap, I
  13.  *   developed this technique contained in DrawTexture. It may not be original,
  14.  *   but I haven't seen it used anywhere else. It can even be augmented with
  15.  *   anti-aliasing for image processing. I release this program and technique
  16.  *   into the public domain, and I hope to create a highly optimized 386
  17.  *   assembler version for my personal library. Please try to credit me when
  18.  *   possible, if this shows you anything new or interesting, and you use it
  19.  *   in any distributed program (Freeware/shareware/commercial).
  20.  *
  21.  *   What this program does:
  22.  *    Draws a bitmap into any 4-sided polygon. First vector is upper-left
  23.  *    second is upper-right, third is lower-right, and last is lower-left.
  24.  *
  25.  *   Limitations:
  26.  *    Don't try to use a "Horizontally convex" polygon.
  27.  *    Undefined results with intersected polygons
  28.  *
  29.  *   What remains to be done:
  30.  *    1. A good intersection-detection routine.
  31.  *    2. A quick 2-D rotation/scaling transform for the corners. I want to
  32.  *       be able to "spin" the bitmap/sprite about a point.
  33.  *    3. Possible, slower alternative to scan "horizontal convex" polygons
  34.  *       and intersected polygons
  35.  *
  36.  */
  37.  
  38. #include <stdio.h>
  39. #include <malloc.h>
  40. #include <string.h>
  41. #include <stdlib.h>
  42. #include <bios.h>
  43. #include <dos.h>
  44. #include "gl.h"
  45. #include <time.h>
  46.  
  47. int YZSize;
  48.  
  49. unsigned char ibuff[65000],ipal[768];
  50.  
  51. struct
  52. {
  53.     char filename[80];
  54.     int  sizex;
  55.     int  sizey;
  56.     unsigned char *buff;
  57.     unsigned char *pal;
  58. } slots[64];
  59.  
  60.  
  61. struct text_s
  62. {
  63.     unsigned char *Buffer;
  64.     int XSize,YSize;
  65. } MyMap;
  66.  
  67.  
  68. struct quad_s
  69. {
  70.     int x[4],y[4];
  71. } MyPoly;
  72.  
  73. void DrawTexture(struct quad_s *poly,struct text_s *Texture,int debug);
  74.  
  75. void OrderPoly(struct quad_s *poly,unsigned char *order);
  76.  
  77. /* This routine eliminates intersections by swapping corners
  78.  * if an intersection exists...
  79.  * "adjacent" segments, by nature, cannot intersect, therefore we only
  80.  * need to check opposite segments (AB,CD & DA,BC)
  81.  * Actually, in retrospect, the poly cannot have "horizontal convexity"
  82.  * That is, the scan algorithm cannot handle more than one chunk, Our
  83.  * test, there for is for opposite corners _NOT_ to be next to one another
  84.  * when ordered...
  85.  */
  86. void UnIntersectQuad(struct quad_s *poly)
  87. {
  88.     unsigned char work_order[4];
  89.     int i;
  90.  
  91.     OrderPoly(poly,work_order);
  92.     /* Top Convexity/intersection */
  93.     switch(work_order[0])
  94.     {
  95.         case 0: /* Test to insure 2 is not adjacent */
  96.             if(work_order[1]==2)
  97.             {
  98.                 /* Swap 1 and 2 */
  99.                 i=poly->x[1];
  100.                 poly->x[1]=poly->x[2];
  101.                 poly->x[2]=i;
  102.                 i=poly->y[1];
  103.                 poly->y[1]=poly->y[2];
  104.                 poly->y[2]=i;
  105.             }
  106.             break;
  107.         case 1: /* Test to insure 3 is not adjacent */
  108.             if(work_order[1]==3)
  109.             {
  110.                 /* Swap 0 and 3 */
  111.                 i=poly->x[0];
  112.                 poly->x[0]=poly->x[3];
  113.                 poly->x[3]=i;
  114.                 i=poly->y[0];
  115.                 poly->y[0]=poly->y[3];
  116.                 poly->y[3]=i;
  117.             }
  118.             break;
  119.         case 2: /* Test to insure 0 is not adjacent */
  120.             if(work_order[1]==0)
  121.             {
  122.                 /* Swap 1 and 2 */
  123.                 i=poly->x[1];
  124.                 poly->x[1]=poly->x[2];
  125.                 poly->x[2]=i;
  126.                 i=poly->y[1];
  127.                 poly->y[1]=poly->y[2];
  128.                 poly->y[2]=i;
  129.             }
  130.             break;
  131.         case 3: /* Test to insure 1 is not adjacent */
  132.             if(work_order[1]==1)
  133.             {
  134.                 /* Swap 0 and 3 */
  135.                 i=poly->x[0];
  136.                 poly->x[0]=poly->x[3];
  137.                 poly->x[3]=i;
  138.                 i=poly->y[0];
  139.                 poly->y[0]=poly->y[3];
  140.                 poly->y[3]=i;
  141.             }
  142.             break;
  143.     }
  144.     OrderPoly(poly,work_order);
  145.     /* BOTTOM Convexity/intersection */
  146.     switch(work_order[3])
  147.     {
  148.         case 0: /* Test to insure 2 is not adjacent */
  149.             if(work_order[2]==2)
  150.             {
  151.                 /* Swap 1 and 2 */
  152.                 i=poly->x[1];
  153.                 poly->x[1]=poly->x[2];
  154.                 poly->x[2]=i;
  155.                 i=poly->y[1];
  156.                 poly->y[1]=poly->y[2];
  157.                 poly->y[2]=i;
  158.             }
  159.             break;
  160.         case 1: /* Test to insure 3 is not adjacent */
  161.             if(work_order[2]==3)
  162.             {
  163.                 /* Swap 0 and 3 */
  164.                 i=poly->x[0];
  165.                 poly->x[0]=poly->x[3];
  166.                 poly->x[3]=i;
  167.                 i=poly->y[0];
  168.                 poly->y[0]=poly->y[3];
  169.                 poly->y[3]=i;
  170.             }
  171.             break;
  172.         case 2: /* Test to insure 0 is not adjacent */
  173.             if(work_order[2]==0)
  174.             {
  175.                 /* Swap 1 and 2 */
  176.                 i=poly->x[1];
  177.                 poly->x[1]=poly->x[2];
  178.                 poly->x[2]=i;
  179.                 i=poly->y[1];
  180.                 poly->y[1]=poly->y[2];
  181.                 poly->y[2]=i;
  182.             }
  183.             break;
  184.         case 3: /* Test to insure 1 is not adjacent */
  185.             if(work_order[2]==1)
  186.             {
  187.                 /* Swap 0 and 3 */
  188.                 i=poly->x[0];
  189.                 poly->x[0]=poly->x[3];
  190.                 poly->x[3]=i;
  191.                 i=poly->y[0];
  192.                 poly->y[0]=poly->y[3];
  193.                 poly->y[3]=i;
  194.             }
  195.             break;
  196.     }
  197.     /* Now for intersection test... */
  198.  
  199. }
  200.  
  201.  
  202. int LoadSlot(int sl,char *fname);
  203. void setcolor(unsigned char c,unsigned char r,unsigned char g,unsigned char b);
  204.  
  205. int lastlength,lastdelta;
  206.  
  207. unsigned char *ScreenPtr;
  208.  
  209. struct Pal_s
  210. {
  211.     unsigned char Red;
  212.     unsigned char Blue;
  213.     unsigned char Green;
  214. };
  215.  
  216.  
  217. /*
  218.  
  219. This algorithm is based on the calculation of the third side of a triangle
  220. given the known two sides are connected by a right angle.
  221. This formula is: a^2+b^2=c^2. a and b are the absolute X-Y deltas.
  222. The first calcluation of c then becomes a, and Z delta becomes b,
  223. and we do it again. While we _HAVE_ to calculate the squares, it is not needed
  224. to calc the roots.
  225.  
  226. i.e. Deltas of 1+1+5=7, 1+2+4=7, but distance is less on second...
  227.                 27        21
  228.  
  229. Thus, we simply add the squares of all of the absolute deltas.
  230.  
  231. */
  232. int FindBestMatch(struct Pal_s *Pal,int r,int g,int b)
  233. {
  234.     int Distance,i,j,k,R,G,B;
  235.  
  236.     k=12288; j=0;
  237.     for(i=0;i<256;i++)
  238.     {
  239.         R=abs(Pal[i].Red-r);
  240.         R*=R;
  241.         G=abs(Pal[i].Green-g);
  242.         G*=G;
  243.         B=abs(Pal[i].Blue-b);
  244.         B*=B;
  245.         Distance=R+G+B;
  246.         if(Distance<k)
  247.         {
  248.             j=i; k=Distance;
  249.         }
  250.     }
  251.     return(j);
  252. }
  253.  
  254. /*
  255.  
  256. A simple routine to draw a four-sided polygon in a given color.
  257.  
  258. */
  259. void DrawPoly(struct quad_s *Poly,int c)
  260. {
  261.     GL_Line(Poly->x[0],Poly->y[0],Poly->x[1],Poly->y[1],c);
  262.     GL_Line(Poly->x[1],Poly->y[1],Poly->x[2],Poly->y[2],c);
  263.     GL_Line(Poly->x[2],Poly->y[2],Poly->x[3],Poly->y[3],c);
  264.     GL_Line(Poly->x[3],Poly->y[3],Poly->x[0],Poly->y[0],c);
  265.     GL_SetPixel(Poly->x[0],Poly->y[0],c);
  266. }
  267.  
  268. unsigned char Order[4];
  269. int WhiteColor,RedColor,BlackColor,GrayColor;
  270. int rcount,lcount,rva[8],rvb[8],lva[8],lvb[8],rcnt[8],lcnt[8];
  271.  
  272. #define ROTATIONS  30
  273.  
  274. /* I wish DJGPP had a decent random macro!!!!
  275.  *  I'll get a 32-bit version done soon
  276.  */
  277. #define RAND(x)  (rand()%x)
  278.  
  279. int NewDir(int x,int y,int olddir);
  280. int UpdateX(int x,int direction);
  281. int UpdateY(int y,int direction);
  282.  
  283. void main(void)
  284. {
  285.     long DeltaX,DeltaY,XSize,YSize;
  286.     int i,j,k,NewY;
  287.     /* GrContext ScrCtx; */
  288.     unsigned char *RPtr;
  289.     unsigned char *BuffPtr;
  290.  
  291.     for(i=0;i<64;i++)
  292.     {
  293.         slots[i].filename[0]=0;
  294.         slots[i].pal=NULL;
  295.         slots[i].buff=NULL;
  296.         slots[i].sizex=0;
  297.         slots[i].sizey=0;
  298.     }
  299.     GL_InitMode13();
  300.     slots[0].buff=ibuff;
  301.     slots[0].pal=ipal;
  302.     GL_Gif("bnbtitle.gif",slots[0].buff,slots[0].pal,&slots[0].sizex,&slots[0].sizey);
  303.     /* LoadSlot(0,"bnbtitle.gif"); */
  304.     MyMap.Buffer=slots[0].buff;
  305.     MyMap.XSize=slots[0].sizex;
  306.     MyMap.YSize=slots[0].sizey;
  307.     for(i=0;i<256;i++)
  308.     {
  309.         /* slots[0].pal[i*3]/=4;
  310.         slots[0].pal[(i*3)+1]/=4;
  311.         slots[0].pal[(i*3)+2]/=4; */
  312.         setcolor(i,
  313.             slots[0].pal[i*3],
  314.                 slots[0].pal[(i*3)+1],
  315.                     slots[0].pal[(i*3)+2]);
  316.     }
  317.     WhiteColor=FindBestMatch((struct Pal_s *)slots[0].pal,63,63,63);
  318.     RedColor=FindBestMatch((struct Pal_s *)slots[0].pal,63,13,13);
  319.     BlackColor=FindBestMatch((struct Pal_s *)slots[0].pal,0,0,0);
  320.     GrayColor=FindBestMatch((struct Pal_s *)slots[0].pal,30,30,30);
  321.     /* GrSaveContext(&ScrCtx); */
  322.     ScreenPtr=(unsigned char *)0x0a0000; /* ScrCtx.gc_baseaddr; */
  323.     RPtr=ScreenPtr;
  324.     XSize=slots[0].sizex*65536;
  325.     YSize=slots[0].sizey*65536;
  326.     DeltaX=XSize/320;
  327.     DeltaY=YSize/200;
  328.     j=0;
  329.     DeltaX=XSize/(320);
  330.     RPtr=ScreenPtr;
  331.     j=0;
  332.     memset(RPtr,0,320*200);
  333.     DeltaX=XSize/320;
  334.     RPtr=ScreenPtr;
  335.     memset(ScreenPtr,BlackColor,320*200);
  336.     MyPoly.x[0]=320/10;
  337.     MyPoly.x[1]=320-(320/15);
  338.     MyPoly.x[2]=320-(320/5);
  339.     MyPoly.x[3]=320/12;
  340.     MyPoly.y[0]=200/20;
  341.     MyPoly.y[1]=200/10;
  342.     MyPoly.y[2]=200-(200/15);
  343.     MyPoly.y[3]=200-(200/25);
  344.     DrawPoly(&MyPoly,WhiteColor);
  345.     DrawTexture(&MyPoly,&MyMap,0);
  346.     while(!kbhit())
  347.     {
  348.         rand();
  349.         for(i=0;i<ROTATIONS;i++)
  350.         {
  351.             rand();
  352.             if(kbhit())
  353.                 break;
  354.             MyPoly.x[0]=(319*(i+1))/ROTATIONS;
  355.             MyPoly.x[1]=319;
  356.             MyPoly.x[2]=319-(319*(i+1))/ROTATIONS;
  357.             MyPoly.x[3]=0;
  358.             MyPoly.y[0]=0;
  359.             MyPoly.y[1]=(199*(i+1))/ROTATIONS;
  360.             MyPoly.y[2]=199;
  361.             MyPoly.y[3]=199-(199*(i+1))/ROTATIONS;
  362.             DrawPoly(&MyPoly,RedColor);
  363.             DrawTexture(&MyPoly,&MyMap,0);
  364.         }
  365.         for(i=0;i<ROTATIONS;i++)
  366.         {
  367.             rand();
  368.             if(kbhit())
  369.                 break;
  370.             MyPoly.x[3]=(319*(i+1))/ROTATIONS;
  371.             MyPoly.x[0]=319;
  372.             MyPoly.x[1]=319-(319*(i+1))/ROTATIONS;
  373.             MyPoly.x[2]=0;
  374.             MyPoly.y[3]=0;
  375.             MyPoly.y[0]=(199*(i+1))/ROTATIONS;
  376.             MyPoly.y[1]=199;
  377.             MyPoly.y[2]=199-(199*(i+1))/ROTATIONS;
  378.             DrawPoly(&MyPoly,WhiteColor);
  379.             DrawTexture(&MyPoly,&MyMap,0);
  380.         }
  381.         for(i=0;i<ROTATIONS;i++)
  382.         {
  383.             rand();
  384.             if(kbhit())
  385.                 break;
  386.             MyPoly.x[2]=(319*(i+1))/ROTATIONS;
  387.             MyPoly.x[3]=319;
  388.             MyPoly.x[0]=319-(319*(i+1))/ROTATIONS;
  389.             MyPoly.x[1]=0;
  390.             MyPoly.y[2]=0;
  391.             MyPoly.y[3]=(199*(i+1))/ROTATIONS;
  392.             MyPoly.y[0]=199;
  393.             MyPoly.y[1]=199-(199*(i+1))/ROTATIONS;
  394.             DrawPoly(&MyPoly,RedColor);
  395.             DrawTexture(&MyPoly,&MyMap,0);
  396.         }
  397.         for(i=0;i<ROTATIONS;i++)
  398.         {
  399.             rand();
  400.             if(kbhit())
  401.                 break;
  402.             MyPoly.x[1]=(319*(i+1))/ROTATIONS;
  403.             MyPoly.x[2]=319;
  404.             MyPoly.x[3]=319-(319*(i+1))/ROTATIONS;
  405.             MyPoly.x[0]=0;
  406.             MyPoly.y[1]=0;
  407.             MyPoly.y[2]=(199*(i+1))/ROTATIONS;
  408.             MyPoly.y[3]=199;
  409.             MyPoly.y[0]=199-(199*(i+1))/ROTATIONS;
  410.             DrawPoly(&MyPoly,WhiteColor);
  411.             DrawTexture(&MyPoly,&MyMap,0);
  412.         }
  413.     }
  414.     while(kbhit())
  415.         getch();
  416.     while(!kbhit())
  417.     {
  418.         rand();
  419.         for(i=0;i<20;i++)
  420.         {
  421.             rand();
  422.             if(kbhit())
  423.                 break;
  424.             MyPoly.x[0]=0-(i*8);
  425.             MyPoly.x[1]=319+(i*8);
  426.             MyPoly.x[2]=319+(i*8);
  427.             MyPoly.x[3]=0-(i*8);
  428.             MyPoly.y[0]=0-(i*8);
  429.             MyPoly.y[1]=0-(i*8);
  430.             MyPoly.y[2]=199+(i*8);
  431.             MyPoly.y[3]=199+(i*8);
  432.             /* DrawPoly(&MyPoly,RedColor); */
  433.             DrawTexture(&MyPoly,&MyMap,0);
  434.         }
  435.         for(i=20;i;i--)
  436.         {
  437.             rand();
  438.             if(kbhit())
  439.                 break;
  440.             MyPoly.x[0]=0-(i*8);
  441.             MyPoly.x[1]=319+(i*8);
  442.             MyPoly.x[2]=319+(i*8);
  443.             MyPoly.x[3]=0-(i*8);
  444.             MyPoly.y[0]=0-(i*8);
  445.             MyPoly.y[1]=0-(i*8);
  446.             MyPoly.y[2]=199+(i*8);
  447.             MyPoly.y[3]=199+(i*8);
  448.             /* DrawPoly(&MyPoly,RedColor); */
  449.             DrawTexture(&MyPoly,&MyMap,0);
  450.         }
  451.     }
  452.     while(kbhit())
  453.         getch();
  454.     i=1;
  455.     j=2;
  456.     k=3;
  457.     NewY=0;   /* Directions of points */
  458.     while(!kbhit())
  459.     {
  460.         MyPoly.x[0]=UpdateX(MyPoly.x[0],i);
  461.         MyPoly.y[0]=UpdateY(MyPoly.y[0],i);
  462.         i=NewDir(MyPoly.x[0],MyPoly.y[0],i);
  463.  
  464.         MyPoly.x[1]=UpdateX(MyPoly.x[1],j);
  465.         MyPoly.y[1]=UpdateY(MyPoly.y[1],j);
  466.         j=NewDir(MyPoly.x[1],MyPoly.y[1],j);
  467.  
  468.         MyPoly.x[2]=UpdateX(MyPoly.x[2],k);
  469.         MyPoly.y[2]=UpdateY(MyPoly.y[2],k);
  470.         k=NewDir(MyPoly.x[2],MyPoly.y[2],k);
  471.  
  472.         MyPoly.x[3]=UpdateX(MyPoly.x[3],NewY);
  473.         MyPoly.y[3]=UpdateY(MyPoly.y[3],NewY);
  474.         NewY=NewDir(MyPoly.x[3],MyPoly.y[3],NewY);
  475.  
  476.         /* memset(RPtr,0,320*200); */
  477.         UnIntersectQuad(&MyPoly);
  478.         DrawTexture(&MyPoly,&MyMap,0);
  479.     }
  480.     while(kbhit())
  481.         getch();
  482.     getch();
  483.     GL_TextMode();
  484.     /* GrSetMode(GR_default_text); */
  485. }
  486.  
  487. /*
  488.  * Convenience function... update the direction, if needed
  489.  */
  490. int NewDir(int x,int y,int olddir)
  491. {
  492.     if(x<=0)
  493.     {
  494.         if(y<=0)
  495.         {
  496.             return(3);
  497.         }
  498.         else
  499.         {
  500.             if(y>=199)
  501.             {
  502.                 return(1);
  503.             }
  504.             return(RAND(3)+1);
  505.         }
  506.     }
  507.     else
  508.     {
  509.         if(x>=319)
  510.         {
  511.             if(y<=0)
  512.             {
  513.                 return(5);
  514.             }
  515.             else
  516.             {
  517.                 if(y>=199)
  518.                 {
  519.                     return(7);
  520.                 }
  521.                 return(RAND(3)+5);
  522.             }
  523.         }
  524.         else
  525.         {
  526.             if(y<=0)
  527.             {
  528.                 return(RAND(3)+3);
  529.             }
  530.             else
  531.             {
  532.                 if(y>=199)
  533.                 {
  534.                     olddir=RAND(3); if(olddir==2) olddir=7;
  535.                     return(olddir);
  536.                 }
  537.                 return(olddir);
  538.             }
  539.         }
  540.     }
  541. }
  542.  
  543. /*
  544.  * Convenience function... update the X-Co-ord given a direction
  545.  */
  546. int UpdateX(int x,int direction)
  547. {
  548.     switch(direction)
  549.     {
  550.         case 0: /* UP */
  551.         case 4:
  552.             return(x);
  553.             break;
  554.         case 1: /* UP-RIGHT */
  555.         case 2:
  556.         case 3:
  557.             return(x+1);
  558.             break;
  559.         case 5:
  560.         case 6:
  561.         case 7:
  562.             return(x-1);
  563.             break;
  564.     }
  565.     return(x);
  566. }
  567.  
  568. /*
  569.  * Convenience function... update the Y-Co-ord given a direction
  570.  */
  571. int UpdateY(int y,int direction)
  572. {
  573.     switch(direction)
  574.     {
  575.         case 2:
  576.         case 6:
  577.             return(y);
  578.             break;
  579.         case 0: /* UP */
  580.         case 1: /* UP-RIGHT */
  581.         case 7:
  582.             return(y-1);
  583.             break;
  584.         case 3:
  585.         case 4:
  586.         case 5:
  587.             return(y+1);
  588.             break;
  589.     }
  590.     return(y);
  591. }
  592.  
  593. void disable(void);
  594. void enable(void);
  595.  
  596.  
  597. #pragma aux disable =  "cli"
  598. #pragma aux enable =   "sti"
  599.  
  600.  
  601.  
  602. /*
  603.  *  Program the RAMDAC 256-color palette. Seems like I'm _ALWAYS_ re-inventing
  604.  *   this one!
  605.  */
  606. void setcolor(unsigned char c,unsigned char r,unsigned char g,unsigned char b)
  607. {
  608.     disable();
  609.     outp(0x3c8,c);
  610.     inp(0x80);
  611.     outp(0x3c9,r);
  612.     inp(0x80);
  613.     outp(0x3c9,g);
  614.     inp(0x80);
  615.     outp(0x3c9,b);
  616.     enable();
  617. }
  618.  
  619. /*
  620.  *  Return an array of vector IDs sorted by Y value
  621.  */
  622. void OrderPoly(struct quad_s *poly,unsigned char *order)
  623. {
  624.     int i,j,x,y;
  625.  
  626.     for(i=0;i<4;i++)
  627.     {
  628.         order[i]=(unsigned char)i;
  629.     }
  630.     for(i=0;i<3;i++)
  631.     {
  632.         for(j=(i+1);j<4;j++)
  633.         {
  634.             if(poly->y[order[j]]<poly->y[order[i]])
  635.             {
  636.                 x=order[i]; order[i]=order[j]; order[j]=x;
  637.             }
  638.         }
  639.     }
  640. }
  641.  
  642.  
  643. /*
  644.  *  General purpose linear conversion routine
  645.  *  I use a more complex version at work that reduces precision to prevent
  646.  *  overflows.
  647.  */
  648. long lconvert(long a,long b,long c)
  649. {
  650.     if(b)
  651.     {
  652.         return((a*c)/b);
  653.     }
  654.     return(0);
  655. }
  656.  
  657. /*
  658.  * Return an arbitrary X point on a given line
  659.  */
  660. int XPoint(int x1,int y1,int x2,int y2,int ny)
  661. {
  662.     int z;
  663.  
  664.     x2-=x1;
  665.     y2-=y1;
  666.     ny-=y1;
  667.     z=lconvert(x2,y2,ny);
  668.     return(z+x1);
  669. }
  670.  
  671. /*
  672.  * Return an arbitrary Y point on a given line
  673.  */
  674. int YPoint(int x1,int y1,int x2,int y2,int nx)
  675. {
  676.     int z;
  677.  
  678.     x2-=x1;
  679.     y2-=y1;
  680.     nx-=x1;
  681.     z=lconvert(y2,x2,nx);
  682.     return(z+y1);
  683. }
  684.  
  685. /*
  686.  * Returns a floating point version of a 16.16 signed fixed point number
  687.  */
  688. float fixed2float(long z)
  689. {
  690.     int sign;
  691.     unsigned long whole,fraction;
  692.     float result;
  693.  
  694.     sign=0;
  695.     if(z<0)
  696.     {
  697.         sign=1;
  698.         z=0-z;
  699.     }
  700.     whole=z>>16;
  701.     fraction=z&0x0ffff;
  702.     result=(float)(fraction); result/=65536.0;
  703.     result+=(float)(whole);
  704.     if(sign) result=0.0-result;
  705.     return(result);
  706. }
  707.  
  708. /*
  709.  * What we do, is for each Screen Y, we draw a line of texture
  710.  *
  711.  *
  712.  * This routine cannot handle "horizontal convexity", that is, when we
  713.  * get two chunks to draw on the same scan line. The program will freak out,
  714.  * so "UnIntersectQuad" is used to "remove" the convexity... normally, you
  715.  * would just avoid this situation. Likewise, the routine doesn't like
  716.  * intersections too much, but surprisingly, the program won't blow any
  717.  * serious chunks, as long as the convexity is taken care of. Images can
  718.  * be flipped, by re-ordering the corners of your polygon.
  719.  * Polygon Co-ordinates can range from -32768 to 32767, as I use SIGNED
  720.  * 16.16bit fixed point numbers.
  721.  *
  722.  *
  723.  */
  724. void DrawTexture(struct quad_s *poly,struct text_s *Texture,int debug)
  725. {
  726.     long i,j,k,ysize;
  727.     long LeftVectorA,LeftVectorB,RightVectorA,RightVectorB;
  728.     long YCheck,LeftSegment,RightSegment,m,n,o,p,q,OSize;
  729.     long LeftDelta,LeftStartX,RightDelta;
  730.     long L_Size,R_Size,LeftBDeltaX,LeftBDeltaY;
  731.     long RightBDeltaX,RightBDeltaY,RightXPos,RightYPos;
  732.     long LeftXPos,LeftYPos,LeftCount,RightCount,LeftX,RightX;
  733.     unsigned char *screenptr;
  734.  
  735.     lcount=rcount=1;
  736.     OrderPoly(poly,Order);  /* Order now holds points from top to bottom */
  737.     ysize=poly->y[Order[3]]-poly->y[Order[0]];    /* Total screen Y Size */
  738.     YZSize=ysize;
  739.     if(ysize<3)                     /* Don't even try if too small */
  740.         return;
  741.     YCheck=poly->y[Order[3]];               /* 'Lowest' Y+some amount */
  742.     /* Now, load data for first two segments... */
  743.     screenptr=ScreenPtr;
  744.     i=320*poly->y[Order[0]];
  745.     screenptr+=i;
  746.     i=0; j=0;  k=0;
  747.     m=(Order[0]+1)%4; n=(Order[0]+3)%4;
  748.     while(i==j && k<3)
  749.     {
  750.         YCheck+=20;
  751.         i=XPoint(poly->x[Order[0]],poly->y[Order[0]],
  752.                 poly->x[m],poly->y[m],YCheck);
  753.         j=XPoint(poly->x[Order[0]],poly->y[Order[0]],
  754.                 poly->x[n],poly->y[n],YCheck);
  755.         k++;
  756.     }
  757.     if(k==3)
  758.     {
  759.         /* Either, invalid, or flat line! */
  760.         i=poly->x[m];  j=poly->x[n];
  761.         if(i==j)
  762.             return;  /* Invalid polygon... */
  763.     }
  764.     LeftVectorA=Order[0];
  765.     RightVectorA=Order[0];
  766.     if(i<j)  /* 0,m is LEFT edge */
  767.     {
  768.         LeftVectorB=m; RightVectorB=n;
  769.         LeftCount=poly->y[LeftVectorB]-poly->y[LeftVectorA];
  770.         RightCount=poly->y[RightVectorB]-poly->y[RightVectorA];
  771.         L_Size=LeftCount;
  772.         R_Size=RightCount;
  773.         i=poly->x[LeftVectorB]-poly->x[LeftVectorA];
  774.         LeftDelta=lconvert(i,LeftCount,65536);
  775.         j=poly->x[RightVectorB]-poly->x[RightVectorA];
  776.         RightDelta=lconvert(j,RightCount,65536);
  777.         LeftX=poly->x[LeftVectorA]*65536;
  778.         RightX=LeftX;
  779.     }
  780.     else
  781.     {
  782.         LeftVectorB=n; RightVectorB=m;
  783.         LeftCount=poly->y[LeftVectorB]-poly->y[LeftVectorA];
  784.  
  785.         RightCount=poly->y[RightVectorB]-poly->y[RightVectorA];
  786.         L_Size=LeftCount;
  787.         R_Size=RightCount;
  788.         i=poly->x[LeftVectorB]-poly->x[LeftVectorA];
  789.         LeftDelta=lconvert(i,LeftCount,65536);
  790.  
  791.         j=poly->x[RightVectorB]-poly->x[RightVectorA];
  792.         RightDelta=lconvert(j,RightCount,65536);
  793.         LeftX=poly->x[LeftVectorA]*65536;
  794.         RightX=LeftX;
  795.     }
  796.     switch((LeftVectorA<<2)|LeftVectorB)
  797.     {
  798.         case 0: /* A-A Impossible */
  799.         case 2: /* A-C Impossible */
  800.         case 5: /* B-B Impossible */
  801.         case 7: /* B-D Impossible */
  802.         case 8: /* C-A Impossible */
  803.         case 10: /* C-C Impossible */
  804.         case 13: /* D-B impossible */
  805.         case 15: /* D-D Impossible */
  806.             break;
  807.         case 1: /* A-B */
  808.             LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
  809.             LeftBDeltaY=0;
  810.             LeftXPos=0; LeftYPos=0;
  811.             break;
  812.         case 3: /* A-D */
  813.             LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
  814.             LeftBDeltaX=0;
  815.             LeftXPos=0; LeftYPos=0;
  816.             break;
  817.         case 4: /* B-A */
  818.             LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
  819.             LeftBDeltaY=0;
  820.             LeftXPos=Texture->XSize-1; LeftYPos=0;
  821.             break;
  822.         case 6: /* B-C */
  823.             LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
  824.             LeftBDeltaX=0;
  825.             LeftXPos=Texture->XSize-1; LeftYPos=0;
  826.             break;
  827.         case 9: /* C-B */
  828.             LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
  829.             LeftBDeltaX=0;
  830.             LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
  831.             break;
  832.         case 11: /* C-D */
  833.             LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
  834.             LeftBDeltaY=0;
  835.             LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
  836.             break;
  837.         case 12: /* D-A */
  838.             LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
  839.             LeftBDeltaX=0;
  840.             LeftXPos=0; LeftYPos=Texture->YSize-1;
  841.             break;
  842.         case 14: /* D-C */
  843.             LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
  844.             LeftBDeltaY=0;
  845.             LeftXPos=0; LeftYPos=Texture->YSize-1;
  846.             break;
  847.     }
  848.     switch((RightVectorA<<2)|RightVectorB)
  849.     {
  850.         case 0: /* A-A Impossible */
  851.         case 2: /* A-C Impossible */
  852.         case 5: /* B-B Impossible */
  853.         case 7: /* B-D Impossible */
  854.         case 8: /* C-A Impossible */
  855.         case 10: /* C-C Impossible */
  856.         case 13: /* D-B impossible */
  857.         case 15: /* D-D Impossible */
  858.             break;
  859.         case 1: /* A-B */
  860.             RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
  861.             RightBDeltaY=0;
  862.             RightXPos=0; RightYPos=0;
  863.             break;
  864.         case 3: /* A-D */
  865.             RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
  866.             RightBDeltaX=0;
  867.             RightXPos=0; RightYPos=0;
  868.             break;
  869.         case 4: /* B-A */
  870.             RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
  871.             RightBDeltaY=0;
  872.             RightXPos=Texture->XSize-1; RightYPos=0;
  873.             break;
  874.         case 6: /* B-C */
  875.             RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
  876.             RightBDeltaX=0;
  877.             RightXPos=Texture->XSize-1; RightYPos=0;
  878.             break;
  879.         case 9: /* C-B */
  880.             RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
  881.             RightBDeltaX=0;
  882.             RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
  883.             break;
  884.         case 11: /* C-D */
  885.             RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
  886.             RightBDeltaY=0;
  887.             RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
  888.             break;
  889.         case 12: /* D-A */
  890.             RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
  891.             RightBDeltaX=0;
  892.             RightXPos=0; RightYPos=Texture->YSize-1;
  893.             break;
  894.         case 14: /* D-C */
  895.             RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
  896.             RightBDeltaY=0;
  897.             RightXPos=0; RightYPos=Texture->YSize-1;
  898.             break;
  899.     }
  900.     LeftXPos*=65536; LeftYPos*=65536;
  901.     RightXPos*=65536; RightYPos*=65536;
  902.     lva[0]=LeftVectorA;
  903.     lvb[0]=LeftVectorB;
  904.     rva[0]=RightVectorA;
  905.     rvb[0]=RightVectorB;
  906.     lcnt[0]=LeftCount;
  907.     rcnt[0]=RightCount;
  908.     for(i=0;i<ysize;i++)
  909.     {
  910.         m=poly->y[Order[0]]+i;
  911.         if(m>199)
  912.             break;
  913.         if(!LeftCount)
  914.         {
  915.             /* Get next Left Vector */
  916.             j=LeftVectorB; k=(LeftVectorB+1)%4;
  917.             if(k==LeftVectorA)
  918.             {
  919.                 k=(LeftVectorB+3)%4;
  920.             }
  921.             LeftVectorA=j; LeftVectorB=k;
  922.             LeftX=poly->x[LeftVectorA]*65536;
  923.             LeftCount=poly->y[LeftVectorB]-poly->y[LeftVectorA];
  924.             lva[lcount]=LeftVectorA;
  925.             lvb[lcount]=LeftVectorB;
  926.             lcnt[lcount]=LeftCount;
  927.             lcount++;
  928.             j=poly->x[LeftVectorB]-poly->x[LeftVectorA];
  929.             L_Size=LeftCount;
  930.             LeftDelta=lconvert(j,LeftCount,65536);
  931.             switch((LeftVectorA<<2)|LeftVectorB)
  932.             {
  933.                 case 0: /* A-A Impossible */
  934.                 case 2: /* A-C Impossible */
  935.                 case 5: /* B-B Impossible */
  936.                 case 7: /* B-D Impossible */
  937.                 case 8: /* C-A Impossible */
  938.                 case 10: /* C-C Impossible */
  939.                 case 13: /* D-B impossible */
  940.                 case 15: /* D-D Impossible */
  941.                     break;
  942.                 case 1: /* A-B */
  943.                     LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
  944.                     LeftBDeltaY=0;
  945.                     LeftXPos=0; LeftYPos=0;
  946.                     break;
  947.                 case 3: /* A-D */
  948.                     LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
  949.                     LeftBDeltaX=0;
  950.                     LeftXPos=0; LeftYPos=0;
  951.                     break;
  952.                 case 4: /* B-A */
  953.                     LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
  954.                     LeftBDeltaY=0;
  955.                     LeftXPos=Texture->XSize-1; LeftYPos=0;
  956.                     break;
  957.                 case 6: /* B-C */
  958.                     LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
  959.                     LeftBDeltaX=0;
  960.                     LeftXPos=Texture->XSize-1; LeftYPos=0;
  961.                     break;
  962.                 case 9: /* C-B */
  963.                     LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
  964.                     LeftBDeltaX=0;
  965.                     LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
  966.                     break;
  967.                 case 11: /* C-D */
  968.                     LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
  969.                     LeftBDeltaY=0;
  970.                     LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
  971.                     break;
  972.                 case 12: /* D-A */
  973.                     LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
  974.                     LeftBDeltaX=0;
  975.                     LeftXPos=0; LeftYPos=Texture->YSize-1;
  976.                     break;
  977.                 case 14: /* D-C */
  978.                     LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
  979.                     LeftBDeltaY=0;
  980.                     LeftXPos=0; LeftYPos=Texture->YSize-1;
  981.                     break;
  982.             }
  983.             LeftXPos*=65536; LeftYPos*=65536;
  984.  
  985.         }
  986.         if(!RightCount)
  987.         {
  988.             /* Get next Right Vector */
  989.             j=RightVectorB; k=(RightVectorB+1)%4;
  990.             if(k==RightVectorA)
  991.             {
  992.                 k=(RightVectorB+3)%4;
  993.             }
  994.             RightVectorA=j; RightVectorB=k;
  995.             RightX=poly->x[RightVectorA]*65536;
  996.             RightCount=poly->y[RightVectorB]-poly->y[RightVectorA];
  997.             R_Size=RightCount;
  998.             rva[rcount]=RightVectorA;
  999.             rvb[rcount]=RightVectorB;
  1000.             rcnt[rcount]=RightCount;
  1001.             rcount++;
  1002.             j=poly->x[RightVectorB]-poly->x[RightVectorA];
  1003.             RightDelta=lconvert(j,RightCount,65536);
  1004.             switch((RightVectorA<<2)|RightVectorB)
  1005.             {
  1006.                 case 0: /* A-A Impossible */
  1007.                 case 2: /* A-C Impossible */
  1008.                 case 5: /* B-B Impossible */
  1009.                 case 7: /* B-D Impossible */
  1010.                 case 8: /* C-A Impossible */
  1011.                 case 10: /* C-C Impossible */
  1012.                 case 13: /* D-B impossible */
  1013.                 case 15: /* D-D Impossible */
  1014.                     break;
  1015.                 case 1: /* A-B */
  1016.                     RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
  1017.                     RightBDeltaY=0;
  1018.                     RightXPos=0; RightYPos=0;
  1019.                     break;
  1020.                 case 3: /* A-D */
  1021.                     RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
  1022.                     RightBDeltaX=0;
  1023.                     RightXPos=0; RightYPos=0;
  1024.                     break;
  1025.                 case 4: /* B-A */
  1026.                     RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
  1027.                     RightBDeltaY=0;
  1028.                     RightXPos=Texture->XSize-1; RightYPos=0;
  1029.                     break;
  1030.                 case 6: /* B-C */
  1031.                     RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
  1032.                     RightBDeltaX=0;
  1033.                     RightXPos=Texture->XSize-1; RightYPos=0;
  1034.                     break;
  1035.                 case 9: /* C-B */
  1036.                     RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
  1037.                     RightBDeltaX=0;
  1038.                     RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
  1039.                     break;
  1040.                 case 11: /* C-D */
  1041.                     RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
  1042.                     RightBDeltaY=0;
  1043.                     RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
  1044.                     break;
  1045.                 case 12: /* D-A */
  1046.                     RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
  1047.                     RightBDeltaX=0;
  1048.                     RightXPos=0; RightYPos=Texture->YSize-1;
  1049.                     break;
  1050.                 case 14: /* D-C */
  1051.                     RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
  1052.                     RightBDeltaY=0;
  1053.                     RightXPos=0; RightYPos=Texture->YSize-1;
  1054.                     break;
  1055.             }
  1056.             RightXPos*=65536; RightYPos*=65536;
  1057.         }
  1058.         /* Now, We can shoot our row... */
  1059.         j=(LeftXPos/65536); j+=((LeftYPos/65536)*Texture->XSize);
  1060.         /* j=offset into bitmap... */
  1061.         k=(RightX-LeftX)/65536;   /* Size of line... */
  1062.         if(m<0) k=0;  /* Skip if above screen */
  1063.         m=LeftX/65536; n=RightX/65536;
  1064.         if((n<0)||(m>319))
  1065.         {
  1066.             k=0; /* No line to be draw... */
  1067.         }
  1068.         if(k)
  1069.         {
  1070.             OSize=k;
  1071.             p=LeftXPos; q=LeftYPos;
  1072.             o=LeftX/65536;
  1073.             if(m<0)
  1074.             {
  1075.                 if((m+k)>0)  /* Clip Left Boundary */
  1076.                 {
  1077.                     m=-m;
  1078.                     p+=(((RightXPos-LeftXPos)/k)*m);
  1079.                     q+=(((RightYPos-LeftYPos)/k)*m);
  1080.                     o+=m;
  1081.                 }
  1082.                 else
  1083.                     k=0;
  1084.             }
  1085.             if(n>319) /* Clip Right boundary */
  1086.             {
  1087.                 n-=319;
  1088.                 k-=n;
  1089.             }
  1090.         }
  1091.         /*
  1092.             This is the "inner" loop. Clipping has already been done.
  1093.             "p" is our fixed point bitmap X position
  1094.             "q" is our fixed point bitmap Y position
  1095.             "m" is our starting screen X position
  1096.         */
  1097.         if(k>2)
  1098.         {
  1099.             m=(RightXPos-LeftXPos)/OSize; n=(RightYPos-LeftYPos)/OSize;
  1100.             /* m and n equal deltas for bitmap ray */
  1101.             if(debug)
  1102.             {
  1103.                 if(getch()==' ')
  1104.                 {
  1105.                     GL_TextMode();
  1106.                     /* GrSetMode(GR_default_text); */
  1107.                     printf("XInc= %f  YInc=%f OSize=%d",fixed2float(m),
  1108.                         fixed2float(n),OSize);
  1109.                     printf("ScreenPos=%d P=%f Q=%f\n",o,
  1110.                         fixed2float(p),fixed2float(q));
  1111.  
  1112.                     printf("LeftX=%f  RightX=%f ",fixed2float(LeftXPos),
  1113.                         fixed2float(RightXPos));
  1114.                     printf("LeftY=%f  RightY=%f ",fixed2float(LeftYPos),
  1115.                         fixed2float(RightYPos));
  1116.                     printf("(%c-%c)/(%c-%c)\n",
  1117.                         LeftVectorA+'A',LeftVectorB+'A',RightVectorA+'A',
  1118.                         RightVectorB+'A');
  1119.                     printf(
  1120.                      "L_Size=%d R_Size=%d LeftCount=%d RightCount=%d\n",
  1121.                        L_Size,R_Size,LeftCount,RightCount);
  1122.                     printf("A(%d,%d) B(%d,%d) C(%d,%d) D(%d,%d)\n",
  1123.                         poly->x[0],poly->y[0],poly->x[1],poly->y[1],
  1124.                         poly->x[2],poly->y[2],poly->x[3],poly->y[3]);
  1125.                     exit(0);
  1126.                 }
  1127.             }
  1128.             for(;k;k--,o++)
  1129.             {
  1130.                 j=(p/65536); j+=((q/65536)*Texture->XSize);
  1131.                 screenptr[o]=Texture->Buffer[j];
  1132.                 p+=m; q+=n;
  1133.             }
  1134.         }
  1135.         /* Ending position in bitmap... */
  1136.         LeftCount--; RightCount--;
  1137.         RightXPos+=RightBDeltaX;
  1138.         RightYPos+=RightBDeltaY;
  1139.         LeftXPos+=LeftBDeltaX;
  1140.         LeftYPos+=LeftBDeltaY;
  1141.         LeftX+=LeftDelta;
  1142.         RightX+=RightDelta;
  1143.         screenptr+=320;
  1144.  
  1145.     }
  1146.  
  1147. }
  1148.  
  1149.  
  1150.  
  1151.